package com.tarena.luban.worker.server.repo;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 *T 实现类中具体做缓存使用的类型
 */
public abstract class AbstractCacheRepository<T> implements InitializingBean {
    @Autowired
    protected StringRedisTemplate stringRedisTemplate;
    protected ValueOperations<String, String> opsForValue=null;
    protected ListOperations<String,String> opsForList=null;

    /**
     * 如果实现了InitializingBean的接口,
     * 只要bean对象创建完毕,属性注入完毕,就会在spring 生命周期中
     * 调用afterPropertiesSet方法
     * @throws Exception
     */
    public void afterPropertiesSet() throws Exception{
        opsForValue = stringRedisTemplate.opsForValue();
        opsForList = stringRedisTemplate.opsForList();
    }
    //处理缓存读和写,改,超时等是在父类公用的代码
    public void setCache(String key,T t){
        setCache(key,t,null,null);
    }
    // set get
    public void setCache(String key, T t, Long time, TimeUnit unit){
        //先将T 序列化成string
        String json = searialize(t);
        if (time == null || unit == null){
            //存储的是永久数据
            opsForValue.set(key,json);
            return;
        }else {
            //string类型的数据
            opsForValue.set(key,json,time,unit);
        }

    }
    public T getCache(String key){
        String json = opsForValue.get(key);
        return desearialize(json);
    }
    public void setCaches(String key,List<T> ts){
        setCaches(key,ts,null,null);
    }
    //对应list 缓存的扩展方法
    public void setCaches(String key, List<T> ts,Long time,TimeUnit unit){
        //将传入的T类型的数据,转化成String的json 一次性写入到redis
        List<String> jsons=new ArrayList<>();
        for (T t : ts) {
            String json = searialize(t);
            jsons.add(json);
        }
        //lpush key json1 json2 json3 json4...
        opsForList.leftPushAll(key,jsons);
        if (time != null && unit != null ){
            //超时的条件参数都不是空,需要对数据做超时处理
        //expire key time
            stringRedisTemplate.expire(key,time,unit);
        }
    }
    //读取 list
    public List<T> getCaches(String key){
        List<String> jsons = opsForList.range(key, 0, -1);
        if (jsons !=null && jsons.size()!=0) {
            List<T> ts = new ArrayList<>();
            for (String json : jsons) {
                T t = desearialize(json);
                ts.add(t);
            }
            return ts;
        }
        return null;
    }

    //序列化 子类实现不同 序列化反序列化的代码不同 交给子类实现
    protected abstract String searialize(T t);
    protected abstract T desearialize(String json);
}
